package com.springboot.demo.lock;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;

/**
 * synchronized 测试
 *
 * -XX:-UseBiasedLocking 禁止偏向锁，默认偏向锁是开启的
 *
 * @author supu
 * @since 2020-08-31 11:00
 **/
public class SynchronizedDemo {

    public static void main(String[] args) {
        System.out.println(VM.current().details());

        A a = new A();
        a.setAge(10);
        a.setName("zs");

       /* ClassLayout c1 = ClassLayout.parseInstance(SynchronizedDemo.class);

        System.out.println(c1.toPrintable());*/

        ClassLayout c2 = ClassLayout.parseInstance(a);

        System.out.println(c2.toPrintable());

        new Thread(() -> {
            synchronized (a){
                System.out.println("*********** a 第一次被锁定后的对象头 markword ***********");
                System.out.println(c2.toPrintable());


                /*synchronized (a){
                    System.out.println("*********** a 第二次被锁定后的对象头 markword ***********");
                    System.out.println(c2.toPrintable());
                }*/

                try {
                    TimeUnit.MILLISECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        try {
            TimeUnit.MILLISECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 当多个线程竞争锁时，偏向锁升级为轻量级锁还是重量级锁的条件时，后者获取锁的线程是否能在指定时间内自旋CAS获取到锁，
        // 如果获取到锁了则升级为轻量级锁，否则升级为重量级锁

        synchronized (a){
            System.out.println("*********** a 第二次被锁定后的对象头 markword ***********");
            System.out.println(c2.toPrintable());
        }

        System.out.println("************ a 释放锁定后的对象头 markword **********");
        System.out.println(c2.toPrintable());

    }

    static class A {
        private int age;
        private String name;

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            A a = (A) o;
            return age == a.age &&
                    Objects.equals(name, a.name);
        }

        @Override
        public int hashCode() {
            return Objects.hash(age, name);
        }
    }
}
